package com.liuh.fram.interceptor;

import com.alibaba.fastjson.JSON;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.PropKit;
import com.liuh.fram.err.ErrRenderType;
import com.liuh.fram.err.Error;
import com.liuh.fram.err.LocalException;
import com.liuh.fram.err.LocalException.ErrorRenderType;
import com.liuh.fram.err.LocalException.ErrorType;
import com.liuh.fram.log.Log4jLogExtra;
import com.liuh.fram.util.EncryptKit;

/**
 * @note 异常拦截器
 * @author liuh
 */
public class ExceptionInterceptor implements Interceptor {

	Log4jLogExtra log4jExtra = new Log4jLogExtra(ExceptionInterceptor.class);

	@Override
	public void intercept(Invocation ai) {
		try {
			ai.invoke();
		} catch (Exception e) {
			log4jExtra.error(e.getMessage(), e);
			Controller controller = ai.getController();
			LocalException er = null;
			if (e.getCause() instanceof LocalException) {
				er = (LocalException) e.getCause();
			} else if (e instanceof LocalException) {
				er = (LocalException) e;
			} else {
				er = new LocalException(ErrorType.defaultErr);
			}
			ErrorRenderType type = outErrRender(ai);
			er.setErrRenderType(type);
			//
			renderErr(controller, er);
		}
	}

	/**
	 * @note 根据注解解析输出类型
	 * @author liuh
	 */
	private ErrorRenderType outErrRender(Invocation ai) {
		boolean flag_method = ai.getMethod().isAnnotationPresent(ErrRenderType.class);
		boolean flag_class = ai.getController().getClass().isAnnotationPresent(ErrRenderType.class);
		if (flag_method) {
			ErrRenderType renderType = ai.getMethod().getAnnotation(ErrRenderType.class);
			return renderType.type();
		} else if (flag_class) {
			ErrRenderType renderType = ai.getController().getClass().getAnnotation(ErrRenderType.class);
			return renderType.type();
		} else {
			return Enum.valueOf(ErrorRenderType.class, PropKit.get("default_errRender"));
		}
	}

	/**
	 * @note 生成错误实体
	 * @author liuh
	 */
	private Error buildErrM(LocalException er) {
		Error errorM = null;
		if (er.getErrorM() != null) {
			// 接口返回的错误实体
			errorM = er.getErrorM();
		} else {
			// 应用程序异常根据错误代码生成错误实体
			errorM = er.buildErrorM();
		}
		return errorM;
	}

	/**
	 * @note 页面传参
	 * @author liuh
	 */
	private void build(Controller controller, Error errorM) {
		controller.setAttr("errCode", errorM.getCode());
		controller.setAttr("errMsg", errorM.getMsg());
	}

	/**
	 * @note 压缩异常信息
	 * @author liuh
	 */
	private String compressErrJson(Error errorM) {
		String errorJson = "";
		try {
			errorJson = EncryptKit.compress_base64(JSON.toJSONString(errorM));
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return errorJson;
	}

	/**
	 * @note 输出错误消息
	 * @author liuh
	 */
	private void renderErr(Controller controller, LocalException er) {
		Error errorM = buildErrM(er);
		switch (er.getErrRenderType()) {
		case PC_view500:
			build(controller, errorM);
			controller.render("/views/base/pc_500.html");
			break;
		case MB_view500:
			build(controller, errorM);
			controller.render("/views/base/mb_500.html");
			break;
		case Compress:
			controller.renderText(compressErrJson(errorM));
			break;
		case NoCompress:
			controller.renderJson(errorM);
			break;
		}
	}

}